package Phase1;

import java.net.UnknownHostException;

/**
 * 
 * This Class contains the information to uniquely identify an application running
 * on a given machine that contains an object specified by a given local id.
 *
 * @Domain
 * all possible combination of valid MachineID, Port, and LocalID. 
 * @author byu.ryanpadilla
 * @invariant
 *  port >= 0 && port <= 65535,  LocalID>0
 * 
 */
public class GlobalID implements java.io.Serializable
{
	private static final long serialVersionUID = 1L;
	private MachineID ID;
	private Port port;
	private LocalID localID;
	public GlobalID()
	{
		ID = new MachineID();
		port = new Port();
		localID = new LocalID();
		
	}
	/**
	 * 
	 * @param mID
	 * machineID
	 * @param lID
	 * local identification
	 * @throws UnknownHostException
	 */
	public GlobalID(String mID, LocalID lID) throws UnknownHostException
	{
		this(mID, 3000, lID);
	}
	
	public GlobalID(int p)
	{
		this.ID = new MachineID();
		this.port = new Port(p);
		this.localID = new LocalID();
	}
	
/**
 * constructor
 * @param mID
 * Machine id that contains IP and Host Name of the target machine.
 * @param p
 * Port number of target machine.
 * @param lID
 * Local id
 * @throws UnknownHostException
 */
	public GlobalID(String mID, int p, LocalID lID) throws UnknownHostException
	{
		this.ID = new MachineID(mID);
		this.port = new Port(p);
		this.localID = lID;
	}
	
	/**
	 * Machine ID getter.
	 * @return
	 * Machine IP address. 
	 */
	public String getMachineIP()
	{
		return this.ID.getIP();
	}
	
	/**
	 * Host Name getter
	 * @return
	 * Host Name of the target Machine.
	 */
	public String getMachineHost()
	{
		return this.ID.getHost();
	}
	/**
	 * Port Number getter.
	 * @return
	 * Port number of the target machine.
	 */
	public int getPort()
	{
		return this.port.getPort();
	}
	/**
	 * Local ID getter.
	 * @return
	 * Local id of the target object.
	 */
	public int getLocalID()
	{
		return this.localID.getLocalID();
	}
/**
 * Compares two global ID to see if they are the same.
 * @return
 * True if this Global ID equals the inputed Global ID
 * False if this Global ID is not equal to the inputed GlobalID
 */
	public boolean equals(Object o)
	{
		if (this == o) 
		{
			return true;
		}
		if (o == null || this.getClass() != o.getClass()) 
		{
			return false;
		}

		if(o instanceof GlobalID)
		{
			boolean result = true;
			final GlobalID TMP = (GlobalID) o;
			
			result = result 
					 && (TMP.getMachineIP().compareTo(this.ID.getIP()) == 0 
					 || TMP.getMachineHost().compareTo(this.ID.getHost()) == 0) 
					 && TMP.getPort() == this.port.getPort() 
					 && this.localID.getLocalID() == TMP.getLocalID();

			return result;
		}		

		return false;

	}
	
	/**
	 * The Hash code is used in conjunction with the equals method to test if
	 * two Objects are the same or not.
	 * @return A Unique Hash code for a Global ID containing a particular  Machine ID,
	 * port, and local ID.
	 */
	
	public int hashCode()
	{
		return ID.hashCode() + port.hashCode() + localID.getLocalID();
	}

	/**
	 * Create a String representation of this Objects Machine ID, Port, and Local ID.
	 * @return String representation of the GlobalID
	 */
	public String toString()
	{
		return "MachineID:\n" + this.ID.toString() 
				+ "Port: " + this.port.getPort() + "\n" + this.localID + "\nHashCode: " + this.hashCode() + "\n";		
	}

}
